/*时间日期控件
 * @Author: kevin.huang 
 * @Date: 2018-07-21 12:28:05 
 * @Last Modified by: kevin.huang
 * @Last Modified time: 2019-05-06 22:30:45
 * Copyright (c): kevin.huang Released under MIT License
 */
/***
 * 2019-05-03 
 * 支持通过input标签的value值初始化
 * ****/
(function (global, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['$B'], function (_$B) {
            return factory(global, _$B);
        });
    } else {
        if (!global["$B"]) {
            global["$B"] = {};
        }
        factory(global, global["$B"]);
    }
}(typeof window !== "undefined" ? window : this, function (window, $B) {
    var $body;
    function _getBody() {
        if (!$body) {
            $body = $(window.document.body).css("position", "relative");
        }
        return $body;
    }
    var def = {
        show: false,
        fixed: false,//是否固定显示
        fitWidth: false, //是否将input宽度和 控件宽度调整一致
        initValue: undefined, //可以是date对象，可以是字符串
        shadow: true,//是否需要阴影
        fmt: 'yyyy-MM-dd hh:mm:ss',
        mutil: false,
        clickHide: false,
        readonly: true,
        isSingel: false, //是否是单列模式
        //时间日期选择范围定义,min/max = now / inputId ,'yyyyy-MM-dd hh:mm:ss' 
        range: { min: undefined, max: undefined },
        onChange: undefined //onChange = function(date){}
    };
    function MyDate(jqObj, opts) {
        $B.extend(this, MyDate);    
        jqObj.addClass("k_calendar_input").attr("autocomplete","off");
        this.opts = $.extend({}, def, opts);
        this.currentDate = new Date();//默认初始化当前时间   
        this.isMonthStyle = this.opts.fmt === "yyyy-MM";
        this.isDayStyle = this.opts.fmt === "yyyy-MM-dd";
        this.isSecondStyle = this.opts.fmt === "yyyy-MM-dd hh:mm:ss";
        this.isTimeStyle = this.opts.fmt === "hh:mm:ss" || this.opts.fmt === "hh:mm";
        if (opts.fitWidth) {
            jqObj.addClass("k_box_size").outerWidth(202);
        }
        var value = jqObj.val();
        if(value !== ""){
            var  currentDate = this._txt2Date(value);
            if(currentDate){
                opts.initValue = currentDate;
            }
        }
        if (opts.isSingel) {
            jqObj.data("_calopt", { range: opts.range, onChange: opts.onChange, initValue: opts.initValue });
            opts.fixed = false;
            opts.show = false;
            var ins = window["_k_calendar_ins_"];
            if (ins) {
                ins.setTarget(jqObj, true);
                return ins;
            } else {
                window["_k_calendar_ins_"] = this;
            }
        }
        var config = $B.config.calendar;
        this.config = config;
        this.target = jqObj;
        var i, len, _this = this;
        this._initValue(true);
        this._bindInputEvents();
        this.jqObj = $("<div class='k_calendar_wrap k_box_size clearfix' style='width:202px;z-index:2147483647;'></div>");
        if(this.opts.fixed){
            this.jqObj.css("z-index",1);
        }
        if (this.opts.shadow) {
            this.jqObj.addClass("k_dropdown_shadow");
        }
        if (this.opts.fixed) {//固定显示
            this.opts.show = true;
        }
        if (!this.opts.show) {
            this.jqObj.hide();
        }
        if(this.isTimeStyle){
            //console.log("仅时间模式》》》》》");
            this.jqObj.outerHeight(250);
            this.createTimeOptList();
        }else{
            /**顶部工具栏**/
            this.headerPanel = $("<div class='k_calendar_pannel k_box_size clearfix' style='padding-left:2px;padding-top:2px;'><span class='_prev_year _event' style='width:24px'><i class='fa fa-angle-double-left'></i></span><span  style='width:21px' class='_prev_month _event'><i class='fa fa-angle-left'></i></span><span class='_cur_year  _event' style='width:46px;'>" + this.year + "</span><span>" + config.year + "</span><span class='_cur_month _event' style='width:28px;' >" + this.month + "</span><span>" + config.month + "</span><span style='width:25px' class='_next_month _event'><i class='fa fa-angle-right'></i></span><span class='_next_year _event' style='width:24px'><i class='fa fa-angle-double-right'></i></span></div>").appendTo(this.jqObj);
            this.bindHeaderPanelEvents();

            /**周**/
            this.weekPanel = $("<div class='k_calendar_week k_box_size' style='padding-left:2px;margin-bottom:5px;'></div>");
            for (i = 0, len = config.weekArray.length; i < len; ++i) {
                $("<span class='k_calendar_week_day'>" + config.weekArray[i] + "</span>").appendTo(this.weekPanel);
            }
            this.weekPanel.appendTo(this.jqObj);

            /**天列表**/
            this.daysPanel = $("<div class='k_calendar_days k_box_size clearfix' style='padding-left:2px;'></div>").appendTo(this.jqObj);
            this.createDays();

            /**时间***/
            this.timePanel = $("<div class='k_calendar_time k_box_size' style='margin:1px 0px;padding-left:2px;text-align:center;'></div>").appendTo(this.jqObj);
            this.createTimeTools();

            /***工具栏***/
            this.toolPanel = $("<div class='k_calendar_bools k_box_size clearfix' style='padding-left:1px;'></div>").appendTo(this.jqObj);
            this.createTools();
        }

        this.setPosition();
        if (this.isDayStyle) {
            this.timePanel.hide();
        }
        if (this.isMonthStyle) {//月模式
            this.daysPanel.hide();
            this.timePanel.hide();
            this.headerPanel.children("._cur_month").trigger("click");
            this.toolPanel.css("margin-top", "168px");
        }
        this.jqObj.appendTo(_getBody());
        var nsId = $B.getUUID();
        $(document).on("click."+nsId,function(e){
            if(_this.hide){
                //console.log("document hiden >>>");
                if(e.target){
                    var $e =  $(e.target);
                    if( $e.hasClass("k_calendar_hours") ||  $e.hasClass("k_calendar_minutes") ||  $e.hasClass("k_calendar_seconds") || $e.hasClass("k_calendar_wrap")){
                        return true;
                    }
                }
                _this.hide();
            }else{
                $(this).off("."+nsId);
            }            
        });
        $(window).on("resize."+nsId,function(){
            if(_this.setPositionByTimer){
                _this.setPositionByTimer();
            }else{                
                $(this).off("."+nsId);
            }            
        });
        _this._setBorderColor();
        this.target.data("calender",this);
        this.nsId = nsId;
    }
    MyDate.prototype = {
        createTimeOptList:function(){
            var el1,el2,el3;
            if(this.opts.fmt === "hh:mm"){/**时分模式   makeNiceScroll***/
                el1=  $("<div class='k_calendar_hours' style='width:50%;height:100%;float:left;text-align:center;'></div>").appendTo(this.jqObj);
                el2= $("<div  class='k_calendar_minutes' style='width:50%;height:100%;float:left;text-align:center;'></div>").appendTo(this.jqObj);
            }else{/**时分秒模式***/
                el1= $("<div class='k_calendar_hours' style='width:33.3333%;height:100%;float:left;text-align:center;'></div>").appendTo(this.jqObj);
                el2= $("<div class='k_calendar_minutes' style='width:33.3333%;height:100%;float:left;text-align:center;'></div>").appendTo(this.jqObj);
                el3= $("<div class='k_calendar_seconds' style='width:33.3333%;height:100%;float:left;text-align:center;'></div>").appendTo(this.jqObj);
            }
            var _this = this;
            var $btn = $("<a style='position:absolute;top:1px ;right:1px;cursor:pointer;line-height:14px;'><i class='fa fa-cancel-circled'></i></a>").appendTo(this.jqObj);
            $btn.click(function(){
                _this.hide();
                return false;
            });
            var wrapHour,wrapMinu,wrapSec ;
            if(el1){
                wrapHour = $B.makeNiceScroll(el1);
            }
            if(el2){
                wrapMinu = $B.makeNiceScroll(el2);
            }
            if(el3){
                wrapSec = $B.makeNiceScroll(el3);
            }         
            var envents = {
                click:function(){
                    var $t = $(this);
                    $t.addClass("actived").siblings().removeClass("actived");
                    var val =  parseInt($t.text());
                    if($t.hasClass("_k_hours")){
                        _this.hour = val;
                    }else if($t.hasClass("_k_minutes")){
                        _this.minutes = val;
                    }else{
                        _this.seconds = val;
                    }
                    var newDate = _this._var2Date();
                    _this._setCurrentDate(newDate);
                    _this.update2target(_this.currentDate);
                    return false;
                }
            };        
            /***** this.hour  this.minutes this.seconds ******/
            var i = 0,txt,$el;            
            while(i < 24){
                txt = i;
                if(i < 10){
                    txt = "0"+i;
                }
                $el = $("<div class='k_calendar_time_opts _k_hours' style='padding-right:15px'>"+txt+"</div>").appendTo(wrapHour).on(envents);
                if(i === _this.hour ){
                    $el.addClass("actived");
                }
                i++;
            }
            this._createMinuAndSecItems(wrapMinu,'_k_minutes',envents);
            if(wrapSec){
                this._createMinuAndSecItems(wrapSec,'_k_seconds',envents);
            }
        },
        _createMinuAndSecItems:function(wrap,cls,envents){
            var  i = 0,txt,$el;
            while(i < 60){
                txt = i;
                if(i < 10){
                    txt = "0"+i;
                }
                $el = $("<div class='k_calendar_time_opts "+cls+"' style='padding-right:15px'>"+txt+"</div>").appendTo(wrap).on(envents);
                if(cls === "_k_minutes"){
                    if(this.minutes === i){
                        $el.addClass("actived");
                    }
                }else if(this.seconds === i){
                    $el.addClass("actived");
                }
                i++;
            }
        },
        _time2fullDateTxt:function(value){
            if(this.isTimeStyle){
                if(/^(20|21|22|23|[0-1]\d)?:?([0-5]\d)?:?([0-5]\d)?$/.test(value)){
                    return this.currentDate.format("yyyy-MM-dd") + " "+value;
                }
            }
            return value;
        },
        /**
         * 根据输入框值 初始化currentDate  year、month变量 
         * isInit 是否是new 初始化调用
         * ***/
        _initValue: function (isInit) {
            var value = this.target.val().leftTrim().rightTrim();
            if (value !== "") {               
                this.currentDate = this._txt2Date(value);
            }
            if (isInit) {
                var initVal = this.opts.initValue;
                if (this.opts.isSingel) {
                    initVal = this.target.data("_calopt").initValue;
                }
                //取 initValue
                if (initVal) {
                    if (typeof initVal === "string") {
                        this.currentDate = this._txt2Date(initVal);
                    } else {
                        this.currentDate = initVal;
                    }
                    this.target.val(this.currentDate.format(this.opts.fmt));
                }
            }
            this._setVarByDate(this.currentDate);
        },
        _callWatcher:function(){
            if(this.onWatcher){//配合双向联动使用
                this.target.data("no2update",true);
                this.onWatcher.call(this);
                this.target.removeData("no2update");
            }
        },
        _bindInputEvents: function () {
            var _this = this;
            var binding = this.target.data("k_calr_ins") === undefined;
            if (this.opts.readonly) {
                this.target.attr("readonly", true);
            } else if (binding) {//启用了用户输入                          
                var onInputEvFn = function () {
                    var v = _this.target.val();
                    var inputDate = _this._txt2Date(v);
                    if (inputDate) {
                        if (_this._beforeChange(inputDate)) {
                            _this._setCurrentDate(inputDate);
                            _this._setVarByDate(inputDate);
                            _this.rebuildDaysUi();
                            _this.updateYearAndMonthUi(_this.currentDate);
                            if (_this.isMonthStyle) {//如果是月模式
                                _this._createMonthOpts();
                            }else if(_this.isTimeStyle){
                                _this.activedTimeUi();
                            }else {
                                _this._updateMinAndCec();
                            }
                            _this._callWatcher();
                        }
                    } else {
                        $B.error(_this.config.error, 2);
                        var srcVal = _this.currentDate.format(_this.opts.fmt);
                        _this.target.val(srcVal);
                    }
                };
                this.hasInputed = false;
                this.target.on("input.calendar", function () {
                    _this.hasInputed = true;
                    clearTimeout(_this.userInputTimer);
                    _this.userInputTimer = setTimeout(function () {
                        onInputEvFn();
                    },1000);
                });
            }
            if (binding) {
                this.target.on("blur.calendar", function () {
                    _this._setBorderColor();
                    if (_this.hasInputed) {
                        _this.hasInputed = false;
                        clearTimeout(_this.userInputTimer);
                        onInputEvFn();
                    }
                }).on("click.calendar", function () {
                    _this._setBorderColor();
                    if (!_this.opts.fixed) {
                        _this.slideToggle();
                    }
                    return false;
                }).on("focus.calendar", function () {
                    if (_this.opts.isSingel) {
                        _this.setTarget($(this), false);
                    }
                    _this._setBorderColor();
                });
                this.target.data("k_calr_ins", this);
                this.target.css("cursor", "pointer");
            }
        },
        activedTimeUi:function(){
            var _this = this;
            //k_calendar_hours k_calendar_minutes k_calendar_seconds
            this.jqObj.children(".k_calendar_hours").find("div.k_calendar_time_opts").each(function(){
                var $t = $(this);
                if(parseInt($t.text()) === _this.hour ){
                    $t.addClass("actived");
                }else{
                    $t.removeClass("actived");
                }
            });
            this.jqObj.children(".k_calendar_minutes").find("div.k_calendar_time_opts").each(function(){
                var $t = $(this);
                if(parseInt($t.text()) === _this.minutes ){
                    $t.addClass("actived");
                }else{
                    $t.removeClass("actived");
                }
            });
            this.jqObj.children(".k_calendar_seconds").find("div.k_calendar_time_opts").each(function(){
                var $t = $(this);
                if(parseInt($t.text()) === _this.seconds ){
                    $t.addClass("actived");
                }else{
                    $t.removeClass("actived");
                }
            });

        },
        _setBorderColor: function () {
            var borderColor = this.target.css("border-color");
            this.jqObj.css("border-color", borderColor);
        },
        _getMinMaxCfg: function (flag) {
            var _date, v;
            var range = this.opts.range;
            if (this.opts.isSingel) {
                range = this.target.data("_calopt").range;
            }
            if (range[flag]) {
                if (range[flag].indexOf("#") > -1) {
                    var input = this.target.data(flag + "_input");
                    if (!input) {
                        input = $(range[flag]);
                        this.target.data(flag + "_input", input);
                    }
                    v = input.val();
                    _date = this._txt2Date(v);
                } else if (range[flag] === "now") {
                    _date = new Date();
                } else {
                    v = range[flag];
                    _date = this._txt2Date(v);
                }
            }
            return _date;
        },
        /****
         * 最小值，最大值非法限制检查
         * ***/
        _legalDate: function (newDate, minDate, maxDate) {
            if (minDate) {
                if (newDate.getTime() < minDate.getTime()) {
                    return this.config.minTip.replace("x", minDate.format(this.opts.fmt));
                }
            }
            if (maxDate) {
                if (newDate.getTime() > maxDate.getTime()) {
                    return this.config.maxTip.replace("x", maxDate.format(this.opts.fmt));
                }
            }
            return "";
        },
        /**时间变更前回调
         * 如果不符合要求，调用this._setVarByDate(this.currentDate); 恢复变量
         * ***/
        _beforeChange: function (newDate) {
            var go = true;
            var minDate = this._getMinMaxCfg("min"),
                maxDate = this._getMinMaxCfg("max");
            var res = this._legalDate(newDate, minDate, maxDate);
            if (res !== "") {
                $B.alert(res, 2.5);
                go = false;
            }
            var changeFn = this.opts.onChange;
            if (this.opts.isSingel) {
                changeFn = this.target.data("_calopt").onChange;
            }
            if (go && typeof changeFn === "function") {
                res = changeFn(newDate, newDate.format(this.opts.fmt));
                if (typeof res !== "undefined" && res !== "") {
                    $B.alert(res, 2.5);
                    go = false;
                }
            }
            if (!go) {//this.currentDate没有被修改, 恢复被修改的变量
                this._setVarByDate(this.currentDate);
            }
            return go;
        },
        /**
         * 绑定顶部年/月改变事件
         * ***/
        bindHeaderPanelEvents: function () {
            var _this = this;
            var clickFn = function () {
                if (_this.hourItsPanel) {
                    _this.hourItsPanel.hide();
                }
                if (_this.mmItsPanel) {
                    _this.mmItsPanel.hide();
                }
                var $t = $(this);
                var newDate = _this._var2Date();//获取当前 this.currentDate的副本，用于加减运算
                var curDay = newDate.getDate();
                var update = true;
                if ($t.hasClass("_prev_year")) {
                    newDate.setFullYear(newDate.getFullYear() - 1);
                } else if ($t.hasClass("_prev_month")) {
                    //兼容有溢出的场景 先取上一个月最大日期
                    var lastMonthDate = new Date(newDate.getFullYear(), newDate.getMonth(), 0, _this.hour, _this.minutes, _this.seconds);
                    if (curDay < lastMonthDate.getDate()) {
                        lastMonthDate.setDate(curDay);
                    }
                    newDate = lastMonthDate;
                } else if ($t.hasClass("_cur_year")) {
                    _this._hideMonthPanel();
                    update = false; //
                    if (_this.yearPanel && _this.yearPanel.css("display") !== "none") {
                        _this.yearPanel.hide(100);
                    } else {
                        _this._createYearOpts(newDate.getFullYear());
                    }
                } else if ($t.hasClass("_cur_month")) {
                    if (_this.yearPanel) {
                        if (_this.isMonthStyle) {//月模式不可以关闭                           
                            return false;
                        }
                        _this.yearPanel.hide();
                    }
                    update = false;
                    if (_this.monthPanel && _this.monthPanel.css("display") !== "none") {
                        _this._hideMonthPanel(100);
                    } else {
                        _this._createMonthOpts();
                    }
                } else if ($t.hasClass("_next_month")) {
                    //需要考虑月溢出场景
                    var nextMonthDate = new Date(newDate.getFullYear(), newDate.getMonth() + 2, 0, _this.hour, _this.minutes, _this.seconds);
                    if (curDay < nextMonthDate.getDate()) {
                        nextMonthDate.setDate(curDay);
                    }
                    newDate = nextMonthDate;
                } else if ($t.hasClass("_next_year")) {
                    newDate.setFullYear(newDate.getFullYear() + 1);
                }
                if (update) {
                    if (_this.yearPanel) {
                        _this.yearPanel.hide();
                    }
                    _this._hideMonthPanel();
                    if (_this._beforeChange(newDate)) { //先调用日期时间变更
                        _this._updateVar(newDate);
                        if (!_this.opts.mutil) {//多选场景不需要更新输入框
                            _this.update2target(newDate);
                        }
                        _this.updateYearAndMonthUi(newDate);
                        _this.rebuildDaysUi(newDate);
                        if (_this.isMonthStyle) {//月模式
                            var curMonth = newDate.getMonth() + 1;
                            _this._activeMonthUi(curMonth);
                        }
                    }
                }
                return false;
            };
            var prevYear = this.headerPanel.children().first().click(clickFn);
            var prevMonth = prevYear.next().click(clickFn);
            var curyear = prevMonth.next().click(clickFn);
            var curMonth = curyear.next().next().click(clickFn);
            var nextMonth = curMonth.next().next().click(clickFn);
            nextMonth.next().click(clickFn);
        },
        /**年点击事件***/
        _yearOnclick: function (e) {
            var _this = e.data._this;
            var $t = $(this);
            var $i = $t.children("i");
            if ($i.length > 0) {
                var startYear;
                if ($i.hasClass("fa-angle-double-left")) {//
                    startYear = parseInt($t.siblings(".k_box_size").first().text()) - 18;
                } else {
                    startYear = parseInt($t.siblings(".k_box_size").last().text()) + 1;
                }
                var startTg = $t.parent().children(".k_box_size").first().next();
                while (startTg.length > 0 && startTg.hasClass("_year_num")) {
                    startTg.text(startYear);
                    if (startYear === _this.year) {
                        startTg.addClass("actived");
                    } else {
                        startTg.removeClass("actived");
                    }
                    startYear++;
                    startTg = startTg.next();
                }
            } else {
                var year = parseInt($t.text());
                _this.year = year;
                var newDate = _this._var2Date();
                if (_this._beforeChange(newDate)) {
                    _this._setCurrentDate(newDate);
                    _this.rebuildDaysUi();
                    _this.updateYearAndMonthUi(_this.currentDate);
                    if (!_this.opts.mutil) {
                        _this.update2target(_this.currentDate);
                    }
                    _this.yearPanel.hide(120);
                }
            }
            return false;
        },
        /**
         * 年选择列表
         * ***/
        _createYearOpts: function (year) {//创建年选项
            var append = false;
            if (this.yearPanel) {
                this.yearPanel.children(".k_box_size").remove();
                this.yearPanel.show();
            } else {
                append = true;
                var _this = this;
                this.yearPanel = $("<div class='k_box_size clearfix k_calendar_ym_panel k_dropdown_shadow' style='padding-left:12px;position:absolute;top:30px;left:0;z-index:2110000000;width:100%;background:#fff;'></div>").appendTo(this.jqObj);
                var $closed = $("<div style='position:absolute;top:-2px;right:5px;width:12px;height:12px;line-height:12px;text-align:center;cursor:pointer;'><i class='fa fa-cancel-2' style='font-size:14px;color:#AAAAB4'></i></div>").appendTo(this.yearPanel);
                $closed.click(function () {
                    _this.yearPanel.hide();
                    return false;
                });
            }
            var startYear = year - 12;
            var help = 22, txt, $it;
            while (help > 0) {
                if (help === 22) {
                    txt = "<i style='font-size:16px;color:#A0BFDE' class='fa fa-angle-double-left'></i>";
                    $it = $("<div class='k_box_size' style='float:left;line-height:20px;padding:5px 5px;cursor:pointer;width:43px;text-align:center;'>" + txt + "</div>").appendTo(this.yearPanel);
                    $it.on("click", { _this: this }, this._yearOnclick);
                }
                txt = startYear;
                $it = $("<div class='k_box_size _year_num' style='float:left;line-height:20px;padding:5px 5px;cursor:pointer;width:43px;text-align:center;'>" + txt + "</div>").appendTo(this.yearPanel);
                if (txt === year) {
                    $it.addClass("actived");
                }
                $it.on("click", { _this: this }, this._yearOnclick);
                if (help === 1) {
                    txt = "<i style='font-size:16px;color:#A0BFDE' class='fa fa-angle-double-right'></i>";
                    $it = $("<div class='k_box_size' style='float:left;line-height:20px;padding:5px 5px;cursor:pointer;width:43px;text-align:center;'>" + txt + "</div>").appendTo(this.yearPanel);
                    $it.on("click", { _this: this }, this._yearOnclick);
                }
                help--;
                startYear++;
            }
            if (append) {
                this.yearPanel.appendTo(this.jqObj);
            }
        },
        /**
         * 月模式下用
         * **/
        _activeMonthUi: function (month) {
            this.monthPanel.children().each(function () {
                var $m = $(this);
                if (month === parseInt($m.text())) {
                    $m.addClass("actived");
                } else {
                    $m.removeClass("actived");
                }
            });
        },
        /**月点击事件**/
        _monthOnclick: function (e) {
            var _this = e.data._this;
            var $t = $(this);
            var month = parseInt($t.text());
            _this.month = month;
            var newDate = _this._var2Date();
            if (_this._beforeChange(newDate)) {
                if (_this.isMonthStyle) {//月模式
                    $t.addClass("actived").siblings().removeClass("actived");
                    if (_this.opts.clickHide) {
                        _this.hide();
                    }
                }
                _this._setCurrentDate(newDate);
                _this.rebuildDaysUi();
                _this.updateYearAndMonthUi(_this.currentDate);
                _this.update2target(_this.currentDate);
                _this._hideMonthPanel();

            }
            return false;
        },
        _hideMonthPanel: function () {
            if (!this.isMonthStyle && this.monthPanel) {
                this.monthPanel.hide(120);
            }
        },
        /***
         * 月选择列表
         * **/
        _createMonthOpts: function () {
            var _this = this;
            if (!this.monthPanel) {
                this.monthPanel = $("<div class='k_box_size clearfix k_calendar_ym_panel' style='padding-bottom:4px; padding-top:8px;padding-left: 18px; position: absolute; top: 30px; left: 0px; z-index: 2100000000; width: 100%; background: rgb(255, 255, 255);'></div>").appendTo(this.jqObj);
                var i = 1, txt, $it;
                while (i < 13) {
                    txt = i;
                    if (i < 10) {
                        txt = "0" + i;
                    }
                    $it = $("<div style='float:left;line-height:32px;padding:5px 5px;cursor:pointer;width:45px;text-align:center;'>" + txt + "</div>").appendTo(this.monthPanel);
                    if (i === this.month) {
                        $it.addClass("actived");
                    }
                    $it.on("click", { _this: this }, this._monthOnclick);
                    i++;
                }
                if (!this.isMonthStyle) {
                    this.monthPanel.addClass("k_dropdown_shadow");
                    var $closed = $("<div style='position:absolute;top:-2px;right:5px;width:12px;height:12px;line-height:12px;text-align:center;cursor:pointer;'><i class='fa fa-cancel-2' style='font-size:14px;color:#AAAAB4'></i></div>").appendTo(this.monthPanel);
                    $closed.click(function () {
                        _this.monthPanel.hide();
                        return false;
                    });
                }
            } else {
                this.monthPanel.show();
                this.monthPanel.children().each(function () {
                    var $s = $(this);
                    if (parseInt($s.text()) === _this.month) {
                        $s.addClass("actived");
                    } else {
                        $s.removeClass("actived");
                    }
                });
            }
        },
        /**底部工具栏按钮***/
        createTools: function () {
            var _this = this;
            var clickFn = function () {
                var $t = $(this);
                if (_this.yearPanel) {
                    _this.yearPanel.hide();
                }
                if (!_this.isMonthStyle && _this.monthPanel) {
                    _this.monthPanel.hide();
                }
                if ($t.hasClass("002")) {
                    var now = new Date();
                    _this.year = now.getFullYear();
                    _this.month = now.getMonth() + 1;
                    _this.day = now.getDate();
                    _this.hour = now.getHours();
                    _this.minutes = now.getMinutes();
                    _this.seconds = now.getSeconds();
                    var newDate = _this._var2Date();
                    if (_this._beforeChange(newDate)) {                       
                        _this._setCurrentDate(newDate);
                        _this.rebuildDaysUi();
                        _this.updateYearAndMonthUi(_this.currentDate);
                        _this.update2target(_this.currentDate);
                        _this._updateTimeUi();
                        if (_this.isMonthStyle) {
                            _this._activeMonthUi(_this.month);
                        }
                        if (_this.opts.clickHide) {
                            _this.hide();
                        }
                    }
                } else if ($t.hasClass("003")) {
                    _this.target.val("");
                    _this.daysPanel.children().removeClass("activted");
                } else {
                    _this.hide();
                }
                return false;
            };
            var b1 = $("<div class='002'>" + this.config.now + "</div>").appendTo(this.toolPanel).click(clickFn);
            var b2 = $("<div class='003'>" + this.config.clear + "</div>").appendTo(this.toolPanel).click(clickFn);
            if(this.opts.fixed){
                b1.width(99);
                b2.width(99);
            }else{
                $("<div class='004'>" + this.config.close + "</div>").appendTo(this.toolPanel).click(clickFn);
            }
        },
        _getStrTime: function () {
            var h = this.hour;
            var m = this.minutes;
            var s = this.seconds;
            if (h < 10) { h = '0' + h; }
            if (m < 10) { m = '0' + m; }
            if (s < 10) { s = '0' + s; }
            return { h: h, m: m, s: s };
        },
        /**时分秒工具栏**/
        createTimeTools: function () {
            var _this = this;
            var onHclick = function () {                
                var $s = $(this);
                var v = $s.text();
                if (_this.userInput.attr("id") === "_k_cal_hour") {
                    _this.hour = parseInt(v);
                } else if (_this.userInput.attr("id") === "_k_cal_minu") {
                    _this.minutes = parseInt(v);
                } else {
                    _this.seconds = parseInt(v);
                }
                var newDate = _this._var2Date();
                if (_this._beforeChange(newDate)) {                    
                    _this.userInput.val(v).removeClass("actived");
                    _this._setCurrentDate(newDate);
                    _this.update2target(newDate);
                    $s.parent().hide();                  
                }
                return false;
            };
            var onClickFn = function () {
                var $t = $(this);               
                if (_this.yearPanel) {
                    _this.yearPanel.hide();
                }
                if (_this.monthPanel && !_this.isMonthStyle) {
                    _this.monthPanel.hide();
                }
                var i, len, $closed,isShow = true;
                var curVal = $t.val(),spanArray;
                if ($t.attr("id") === "_k_cal_hour") {
                    if (_this.mmItsPanel) {
                        _this.mmItsPanel.hide();
                    }       
                    if (!_this.hourItsPanel) {
                        _this.hourItsPanel = $("<div class='k_box_size clearfix k_calendar_hours_panel k_dropdown_shadow' style='padding-bottom:2px;padding-left: 12px; position: absolute; top: 30px; left: 0px; z-index: 2112000000; width: 100%; background: rgb(255, 255, 255);'></div>");
                        for (i = 0; i < 24; i++) {
                            $("<span>" + (i < 10 ? '0' + i : i) + "</span>").appendTo(_this.hourItsPanel).click(onHclick);
                        }
                        _this.hourItsPanel.appendTo(_this.jqObj);
                        $closed = $("<div style='position:absolute;top:-2px;right:5px;width:12px;height:12px;line-height:12px;text-align:center;cursor:pointer;'><i class='fa fa-cancel-2' style='font-size:14px;color:#AAAAB4'></i></div>").appendTo(_this.hourItsPanel);
                        $closed.click(function () {
                            _this.hourItsPanel.hide();
                            _this.userInput.removeClass("actived");
                            return false;
                        });
                    } else {
                        if (_this.hourItsPanel.css("display") === "none") {
                            _this.hourItsPanel.show();
                        } else {
                            _this.hourItsPanel.hide();
                            isShow = false;
                        }
                    }                  
                    if(isShow){                       
                        spanArray = _this.hourItsPanel.children("span");
                    }                 
                } else {
                    if (_this.hourItsPanel) {
                        _this.hourItsPanel.hide();
                    }
                    if (!_this.mmItsPanel) {
                        _this.mmItsPanel = $("<div class='k_box_size clearfix k_calendar_mm_panel k_dropdown_shadow' style='padding-top:0px;padding-left: 12px; position: absolute; top: 29px; left: 0px; z-index: 2112000000; width: 100%; background: rgb(255, 255, 255);'></div>");
                        for (i = 0; i < 60; i++) {
                            $("<span>" + (i < 10 ? '0' + i : i) + "</span>").appendTo(_this.mmItsPanel).click(onHclick);
                        }
                        _this.mmItsPanel.appendTo(_this.jqObj);
                        $closed = $("<div style='position:absolute;top:-2px;right:5px;width:12px;height:12px;line-height:12px;text-align:center;cursor:pointer;'><i class='fa fa-cancel-2' style='font-size:14px;color:#AAAAB4'></i></div>").appendTo(_this.mmItsPanel);
                        $closed.click(function () {
                            _this.mmItsPanel.hide();
                            _this.userInput.removeClass("actived");
                            return false;
                        });
                    } else {
                        if (_this.mmItsPanel.css("display") === "none") {
                            _this.mmItsPanel.show();
                        } else {
                            if(_this.userInput && _this.userInput[0] === $t[0]){
                                _this.mmItsPanel.hide();
                                isShow = false;
                            }                         
                        }
                    }
                    if(isShow){                       
                        spanArray = _this.mmItsPanel.children("span");
                    }
                }
                _this.userInput = $t;
                if(isShow){
                    $t.addClass("actived").siblings().removeClass("actived");
                    spanArray.each(function(){
                        var $s = $(this);
                        if($s.text() === curVal){
                            $s.addClass("actived");
                        }else{
                            $s.removeClass("actived");
                        }
                    });                       
                }else{
                    $t.removeClass("actived");
                }
                return false;
            };
            var s = this._getStrTime();
            this.$hour = $("<input readonly='readonly' style='width:30px;text-align:center;' id='_k_cal_hour' value='" + s.h + "'/>").appendTo(this.timePanel).click(onClickFn);
            this.timePanel.append("<span>：</span>");
            this.$minutes = $("<input  readonly='readonly' style='width:30px;text-align:center' id='_k_cal_minu' value='" + s.m + "'/>").appendTo(this.timePanel).click(onClickFn);
            if (this.isSecondStyle) {
                this.timePanel.append("<span>：</span>");
                this.$seconds = $("<input  readonly='readonly' style='width:30px;text-align:center' id='_k_cal_secs' value='" + s.s + "'/>").appendTo(this.timePanel).click(onClickFn);
            }
        },
        _updateTimeUi:function(){
            var s = this._getStrTime();
            if(this.$hour){
                this.$hour.val(s.h);
            }
            if(this.$minutes){
                this.$minutes.val(s.m);
            }
            if(this.$seconds){
                this.$seconds.val(s.s);
            }
        },
        /**
         * 更新时分秒 下拉框
         * ***/
        _updateMinAndCec: function () {
            var s = this._getStrTime();
            if (this.$hour) {
                this.$hour.val(s.h);
            }
            if (this.$minutes) {
                this.$minutes.val(s.m);
            }
            if (this.$seconds) {
                this.$seconds.val(s.s);
            }
        },
        /**
         * 根据newDate新时间重建列表,
         * ****/
        rebuildDaysUi: function (newDate) {
            if (newDate) {
                this.year = newDate.getFullYear();
                this.month = newDate.getMonth() + 1;
            }
            if(this.daysPanel){
                var startDate = this._getStartDate();
                var day, month, tmpStr;
                var one = this.daysPanel.children().first();
                while (one.length > 0) {
                    day = startDate.getDate();
                    month = startDate.getMonth() + 1;
                    tmpStr = startDate.format("yyyy-MM-dd");
                    if (month !== this.month) {
                        one.addClass("day_dull").removeClass("activted").attr("title", tmpStr);
                    } else {
                        one.removeClass("day_dull").removeAttr("title");
                        if (day === this.day) {
                            one.addClass("activted");
                        } else {
                            one.removeClass("activted");
                        }
                    }
                    one.text(day).attr("t", tmpStr);
                    startDate.setDate(startDate.getDate() + 1);
                    one = one.next();
                }
            }       
        },
        /**
         * 根据新时间更新年月ui
         * ***/
        updateYearAndMonthUi: function (newDate) {
            if(this.headerPanel){
                var year = newDate.getFullYear();
                var monthIdx = newDate.getMonth();
                var month = this.config.monthArray[monthIdx];
                this.headerPanel.children("._cur_year").text(year).next().next().text(month);
            }            
        },
        /**
         * 将date根据 config.fmt格式化后设置到target中
         * isCancel 多选场景下，是否是取消
         * ***/
        update2target: function (date, isCancel) {
            var strValue = date.format(this.opts.fmt);
            this.target.val(strValue);
            this._callWatcher();
        },
        /***
         * 根据this.year,this.month 获取星期日开始时间
         * ***/
        _getStartDate: function () {
            var curMonthIdx = this.month - 1;
            var curMonthFisrtDate = new Date(this.year, curMonthIdx, 1);
            var weekDay = curMonthFisrtDate.getDay();
            var startDate = new Date(curMonthFisrtDate);
            while (weekDay > 0) {
                startDate.setDate(startDate.getDate() - 1);
                weekDay--;
            }
            return startDate;
        },
        _dayOnclick: function (e) {
            var _this = e.data._this;
            var $t = $(this);
            var arr = $t.attr("t").split("-");
            _this.year = parseInt(arr[0]);
            _this.month = parseInt(arr[1]);
            _this.day = parseInt(arr[2]);
            var newDate = _this._var2Date();
            if (_this._beforeChange(newDate)) {
                _this._setCurrentDate(newDate);
                _this.updateYearAndMonthUi(_this.currentDate);
                _this.update2target(_this.currentDate);
                $t.addClass("activted").siblings().removeClass("activted");
                if (_this.opts.clickHide) {
                    _this.hide();
                }
            }
            return false;
        },
        /**
         * 创建天日期列表
         * ****/
        createDays: function () {
            var curMonthIdx = this.month - 1;
            var startDate = this._getStartDate();
            var count = 42, tmpStr, tmpSpan, tmpDay, tmpMonth;
            while (count > 0) {
                tmpStr = startDate.format("yyyy-MM-dd");
                tmpDay = startDate.getDate();
                tmpMonth = startDate.getMonth();
                tmpSpan = $("<span t='" + tmpStr + "'>" + tmpDay + "</span>").appendTo(this.daysPanel);
                if (curMonthIdx !== tmpMonth) {
                    tmpSpan.addClass("day_dull").attr("title", tmpStr);
                } else {
                    if (tmpDay === this.day) {
                        tmpSpan.addClass("activted");
                    }
                }
                tmpSpan.on("click", { _this: this }, this._dayOnclick);
                startDate.setDate(startDate.getDate() + 1);
                count--;
            }
        },
        /***
         * 将用户输入的时间字符串转为Date对象
         * ***/
        _txt2Date: function (txtDate) {
            if (txtDate === "") {
                return undefined;
            }   
            txtDate = this._time2fullDateTxt(txtDate); 
            /*****解决 2019-11 格式配置错误的问题 ******/           
            var arrTmp = [],
                year ,
                month ,
                day = 1,
                hour = 0,
                minutes = 0,
                seconds = 0;
            if(txtDate.indexOf('-') > 0 ){
                arrTmp = txtDate.split('-');
            }else if(txtDate.indexOf('/') > 0 ){
                arrTmp = txtDate.split('/');
            }
            if(arrTmp.length === 2){
                year = arrTmp[0];
                month =  parseInt(arrTmp[1]) - 1;                
            }else{
                var m = txtDate.match(/^(\s*\d{4}\s*)(-|\/)\s*(0?[1-9]|1[0-2]\s*)(-|\/)?(\s*[012]?[0-9]|3[01]\s*)?\s*([01]?[0-9]|2[0-4]\s*)?:?(\s*[012345]?[0-9]|\s*)?:?(\s*[012345]?[0-9]\s*)?$/);
                if (m === null || !m[1] && !m[3]) {
                    return undefined;
                }
                year = parseInt(m[1]),
                month = parseInt(m[3]) - 1; 
                if (m[5]) {
                    day = parseInt(m[5]);
                }
                if (m[6]) {
                    hour = parseInt(m[6]);
                }
                if (m[7]) {
                    minutes = parseInt(m[7]);
                }
                if (m[8]) {
                    seconds = parseInt(m[8]);
                }
            }
            var date = new Date(year, month, day, hour, minutes, seconds);
            return date;
        },
        /*** 
         * 将date对象提取year、month、day设置到变量this.year,this.month......
         * ***/
        _setVarByDate: function (date) {
            this.year = date.getFullYear();
            this.month = date.getMonth() + 1;
            this.day = date.getDate();
            this.hour = date.getHours();
            this.minutes = date.getMinutes();
            this.seconds = date.getSeconds();
        },
        /***
         * this.year,this.month 转为 date对象返回
         * ***/
        _var2Date: function () {
            //存在bug，this.day,29,30,31可能是不存在的，需要修正
            try {
                var tmpDate = new Date(this.year, this.month, 0);
                var maxDay = tmpDate.getDate();
                if (this.day > maxDay) {
                    this.day = maxDay;
                }
                var date = new Date(this.year, this.month - 1, this.day, this.hour, this.minutes, this.seconds);
                return date;
            } catch (ex) {
                $B.error(this.config.error);
                return undefined;
            }
            return date;
        },
        /**
         * 将date参数设置到currentDate
         * ***/
        _setCurrentDate: function (date) {
            this.currentDate = date;
            /**适配验证***/            
            if(this.target.hasClass("k_input_value_err")){
                this.target.removeClass("k_input_value_err");
                this.target.siblings(".k_validate_tip_wrap").remove();
            }
        },
        /***
         * 将newDate更新至 currentDate及year\month\day变量
         * ***/
        _updateVar: function (newDate) {
            this._setCurrentDate(newDate);
            this._setVarByDate(newDate);
        },
        setPositionByTimer: function () {
            var _this = this;
            if (_this.t1) {
                var t2 = new Date();
                if ((t2.getTime() - _this.t1.getTime()) > 1000) {
                    _this.setPosition();
                    _this.t1 = t2;
                }
            } else {
                _this.t1 = new Date();
            }
            clearTimeout(this.positionTimer);
            this.positionTimer = setTimeout(function () {
                if(_this.setPosition){
                    _this.setPosition();
                }              
            },500);
        },
        setPosition: function () {
           // console.log("setPosition  >>>>>>");
            var ofs = this.target.offset();
            var css, height;
            if (this._isTopPosition()) {
                height = this._getPanelHeight();
                css = { top: ofs.top - height, left: ofs.left };
            } else {
                height = this.target.outerHeight() - 1;
                css = { top: ofs.top + height, left: ofs.left };
            }
            this.jqObj.css(css);
        },
        slideToggle: function () {
            if (this.jqObj.css("display") === "none") {
                this.show();
            } else {               
                this.hide();
            }
        },
        _getPanelHeight: function () {
            var height = 276;
            if (this.isMonthStyle || this.isDayStyle || this.isTimeStyle) {
                height = 250;
            }
            return height;
        },
        _isTopPosition: function () {
            var bodyHeight = _getBody().height();
            var h = this.target.offset().top + this.target.outerHeight() + this._getPanelHeight();
            if ((h - bodyHeight) > 0) {
                return true;
            }
            return false;
        },
        hide: function () {
            if (this.opts.fixed) {
                return;
            }
            if (this.hourItsPanel) {
                this.hourItsPanel.hide();
            }
            if (this.mmItsPanel) {
                this.mmItsPanel.hide();
            }
            if (this._isTopPosition()) {
                this.jqObj.hide();
            } else {
                this.jqObj.slideUp(200);
            }
            if (this.yearPanel) {//恢复ui
                this.yearPanel.hide();
            }
            this._hideMonthPanel();
        },
        show: function () {
            if (this.opts.fixed) {
                return;
            }
            this.setPosition();
            if (this._isTopPosition()) {
                this.jqObj.show();
            } else {
                this.jqObj.slideDown(200);
            }
        },
        /***
         * 设置时间 date = New Date / yyyy-MM-dd 
         * ***/
        setValue: function (date) {
            var newDate;
            if (typeof date === "string") {
                newDate = this._txt2Date(date);
            } else {
                newDate = date;
            }
            this._setCurrentDate(newDate);
            this._setVarByDate(newDate);
            this.rebuildDaysUi();
            this.updateYearAndMonthUi(this.currentDate);
            this._updateMinAndCec();
            if (!this.opts.mutil) {
                this.update2target(this.currentDate);
            }
        },
        setTarget: function (target, isInit) {
            if (this.target && this.target[0] !== target[0]) {
                if (this.jqObj.css("display") !== "none") {
                    this.jqObj.hide();
                }
            }
            this.target = target;
            this._bindInputEvents();
            this._initValue(isInit);
            this.rebuildDaysUi();
            this.updateYearAndMonthUi(this.currentDate);
            this._updateMinAndCec();
        },
        destroy:function(){          
            this.target.off(".calendar");
            this.target.removeData("k_calr_ins");
            this.target.removeData("calender");
            this.target.removeData("_calopt");
            $(document).off("."+this.nsId);
            this.super.destroy.call(this);
        }
    };
    $B["Calendar"] = MyDate;
    return MyDate;
}));